/*
 * @Descripttion : tip 构造函数 (confirmtip, tooltip)
 * @Author       : QianFox Team
 * @Date         : 2022-05-05 14:19:16
 * @LastEditors  : QianFox Team
 * @LastEditTime : 2022-08-22 16:10:42
 */

import { _typeOf, _throttle } from './common/utils';
import { _foxId, _zIndex } from './common/variables';

function Tip() {
    // 组件内使用
    this.foxId = `foxid${_foxId()}`;
    this.CHILDLIST = ['confirmtip'];
    this.SCROLL = '.foxui-scroll-container'; // 监听此窗口内弹出框位置，并实时设置位置

    // 传入数据及配置
    this.content = '';
    this.placement = ['bottom', 'center']; // 小三角形的位置的
    this.className = '';
    this.width = 'auto';
    this.isRemove = false;

    // 组件内计算值
    this.top = '0';
    this.left = '0';
}

Tip.prototype._html = function () {
    return [
        `<div class="${this.CLASS_NAME}__wrapper ${this.className ? this.className : ''} ${this.effect ? this.effect : ''}" id="${this.foxId}" style="width:${this.width}">`,
        `<div class="${this.CLASS_NAME}">`,
        `${this._headerHtml()}`,
        `<div class="${this.CLASS_NAME}__body">`,
        `${this.content ? this.content : ''}`,
        '</div>',
        `${this._footerHtml()}`,
        '</div>',
        `<div class="${this.CLASS_NAME}-caret"></div>`,
        '</div>',
    ].join('');
};

Tip.prototype._headerHtml = function () {
    return '';
};

Tip.prototype._footerHtml = function () {
    return '';
};

/**
 * @description: 显示/关闭弹出框
 * @param {*}
 * @return {*}
 * @Date: 2022-05-06 10:09:30
 */
Tip.prototype._toggle = function () {
    let isActive = $(`#${this.foxId}`).css('display') !== 'none';

    // 清空弹出框
    this._clearTip();
    // 显示弹出框
    if (!isActive) {
        this._show();
    }
};

/**
 * @description: 显示弹出框
 * @param {*}
 * @return {*}
 * @Date: 2022-05-06 08:36:41
 */
Tip.prototype._show = function () {
    // 计算位置
    this._calcPosition();
    // 设置层级
    $(`#${this.foxId}`).css('z-index', _zIndex());
    // 显示弹出框
    $(`#${this.foxId}`).fadeIn('fast');
};

/**
 * @description: 绑定取消
 * @param {*}
 * @return {*}
 * @Date: 2022-05-05 17:49:52
 */
Tip.prototype._bindCancel = function () {
    let that = this;
    $(document).on('click', this.HANDLE_CANCEL, function () {
        that._close(this);
        if (_typeOf(that.cancel) === 'function') {
            that.cancel();
        }
    });
};

/**
 * @description: 绑定确定
 * @param {*}
 * @return {*}
 * @Date: 2022-05-05 18:06:12
 */
Tip.prototype._bindConfirm = function () {
    let that = this;
    $(document).on('click', this.HANDLE_CONFIRM, function () {
        that._confirm(this);
    });
};

/**
 * @description: 关闭当前弹出框
 * @param {*} el         传取消按钮节点，不传利用 foxId 查找
 * @return {*}
 * @Date: 2022-05-05 17:49:27
 */
Tip.prototype._close = function (el) {
    let that = this;
    if (el) {
        $(el)
            .closest(`.${this.CLASS_NAME}__wrapper`)
            .fadeOut('fast', function () {
                if (that.isRemove) $(this).remove();
            });
    } else {
        $(`#${this.foxId}`).fadeOut('fast', function () {
            if (that.isRemove) $(this).remove();
        });
    }
};

/**
 * @description: 确定
 * @param {*} el
 * @return {*}
 * @Date: 2022-05-05 18:04:03
 */
Tip.prototype._confirm = function (el) {
    // 关闭弹框
    this._close(el);
    // 执行回调函数
    if (_typeOf(this.confirm) === 'function') {
        this.confirm();
    }
};

/**
 * @description: 清空弹出框
 * @param {*}
 * @return {*}
 * @Date: 2022-05-05 17:49:14
 */
Tip.prototype._clearTip = function () {
    this.CHILDLIST.forEach(item => {
        $('.foxui-' + item + '__wrapper').each(function () {
            let $menu = $(this),
                isActive = $menu.css('display') !== 'none';
            if (isActive) {
                $menu.fadeOut('fast');
            }
        });
    });
};

/**
 * @description: 计算并设置弹出框的位置
 * @param {*}
 * @return {*}
 * @Date: 2022-05-06 15:36:27
 */
Tip.prototype._calcPosition = function () {
    let $this = $(this.el),
        len = $this.length;

    // 判断目标元素是存在页面中(避免元素不存在是出错)
    if (len < 1) {
        return false;
    }

    // target -> el
    let target = $this[0],
        clientHeight = document.documentElement.clientHeight, // 可视窗口高度
        clientWidth = document.documentElement.clientWidth; // 可视窗口宽度

    let targetTop = target.getBoundingClientRect().top, // 目标元素的顶部距离
        targetBottom = target.getBoundingClientRect().bottom, // 目标元素的底部距离
        targetLeft = target.getBoundingClientRect().left, // 目标元素的左边距离
        targetRight = target.getBoundingClientRect().right, // 目标元素的右边距离
        targetHeight = target.getBoundingClientRect().height, // 目标元素的高
        targetWidth = target.getBoundingClientRect().width; // 目标元素的宽

    let $menu = $(`#${this.foxId}`), // 弹出框
        menuHeight = $menu.height(), // 弹出框 的高度
        menuWidth = $menu.width(); // 弹出框 的宽度

    let scrollTop = $(document).scrollTop(), // 滚动条高度滚动距离
        placement = [];

    if (this.placement[0] === 'top' || this.placement[0] === 'bottom') {
        // 计算上下距离
        if (clientHeight - targetBottom - 24 > menuHeight && targetTop - 24 <= menuHeight) {
            // 1、下距离
            placement[0] = 'bottom';
            this.top = parseInt(targetBottom) + parseInt(scrollTop) + 12 + 'px';
        } else if (clientHeight - targetBottom - 24 <= menuHeight && targetTop - 24 > menuHeight) {
            // 2、上距离
            placement[0] = 'top';
            this.top = parseInt(targetTop) - parseInt(menuHeight) + parseInt(scrollTop) - 12 + 'px';
        } else {
            // 3、原始位置（上下距离都够 || 上下距离都不够）
            if (this.placement[0] === 'bottom') {
                placement[0] = 'bottom';
                this.top = parseInt(targetBottom) + parseInt(scrollTop) + 12 + 'px';
            } else if (this.placement[0] === 'top') {
                placement[0] = 'top';
                this.top = parseInt(targetTop) - parseInt(menuHeight) + parseInt(scrollTop) - 12 + 'px';
            }
        }

        // 计算左右距离
        if (targetLeft <= menuWidth && clientWidth - targetLeft > menuWidth) {
            // 1、左距离
            placement[1] = 'start';
            this.left = parseInt(targetLeft) + 'px';
        } else if (targetLeft > menuWidth && clientWidth - targetLeft <= menuWidth) {
            // 2、右距离
            placement[1] = 'end';
            this.left = parseInt(targetLeft) - parseInt(menuWidth) + parseInt(targetWidth) + 'px';
        } else if (targetLeft > menuWidth / 2 && clientWidth - targetLeft > menuWidth / 2 && (targetLeft <= menuWidth || clientWidth - targetLeft <= menuWidth)) {
            // 3、中间距离
            placement[1] = 'center';
            this.left = parseInt(targetLeft) - parseInt(menuWidth) / 2 + parseInt(targetWidth) / 2 + 'px';
        } else {
            // 4、原始位置（左右距离都够 || 左右距离都不够）
            placement[1] = this.placement[1];
            if (this.placement[1] === 'start') {
                this.left = parseInt(targetLeft) + 'px';
            } else if (this.placement[1] === 'center') {
                this.left = parseInt(targetLeft) - parseInt(menuWidth) / 2 + parseInt(targetWidth) / 2 + 'px';
            } else if (this.placement[1] === 'end') {
                this.left = parseInt(targetLeft) - parseInt(menuWidth) + parseInt(targetWidth) + 'px';
            }
        }
    }

    if (this.placement[0] === 'left' || this.placement[0] === 'right') {
        // 计算左右距离
        if (targetLeft - 12 > menuWidth && clientWidth - targetLeft - targetWidth - 12 <= menuWidth) {
            // 1、左距离
            placement[0] = 'left';
            this.left = parseInt(targetLeft) - parseInt(menuWidth) - 12 + 'px';
        } else if (targetLeft - 12 <= menuWidth && clientWidth - targetLeft - targetWidth - 12 > menuWidth) {
            // 2、右距离
            placement[0] = 'right';
            this.left = parseInt(targetRight) + 12 + 'px';
        } else {
            // 3、原始位置（左右距离都够 || 左右距离都不够）
            if (this.placement[0] === 'left') {
                placement[0] = 'left';
                this.left = parseInt(targetLeft) - parseInt(menuWidth) - 12 + 'px';
            } else if (this.placement[0] === 'right') {
                placement[0] = 'right';
                this.left = parseInt(targetRight) + 12 + 'px';
            }
        }

        // 计算上下距离
        if (clientHeight - targetBottom > menuHeight && targetTop <= menuHeight) {
            // 1、下距离
            placement[1] = 'start';
            this.top = parseInt(targetTop) + parseInt(scrollTop) + 'px';
        } else if (clientHeight - targetBottom <= menuHeight && targetTop > menuHeight) {
            // 2、上距离
            placement[1] = 'end';
            this.top = parseInt(targetBottom) + parseInt(scrollTop) - parseInt(menuHeight) + 'px';
        } else if (
            clientHeight - targetBottom - scrollTop > menuHeight / 2 &&
            targetTop - scrollTop > menuHeight / 2 &&
            (clientHeight - targetBottom - scrollTop <= menuHeight || targetTop - scrollTop <= menuHeight)
        ) {
            // 3、中间距离
            placement[1] = 'center';
            this.top = parseInt(targetTop) + parseInt(scrollTop) + parseInt(targetHeight) / 2 - parseInt(menuHeight) / 2 + 'px';
        } else {
            // 4、原始位置（上下距离都够 || 上下距离都不够）
            placement[1] = this.placement[1];
            if (this.placement[1] === 'start') {
                this.top = parseInt(targetTop) + parseInt(scrollTop) + 'px';
            } else if (this.placement[1] === 'center') {
                this.top = parseInt(targetTop) + parseInt(scrollTop) + parseInt(targetHeight) / 2 - parseInt(menuHeight) / 2 + 'px';
            } else if (this.placement[1] === 'end') {
                this.top = parseInt(targetBottom) + parseInt(scrollTop) - parseInt(menuHeight) + 'px';
            }
        }
    }

    // 设置 top left
    $menu.css({ top: this.top, left: this.left });
    // 设置 x-placement 属性
    $menu.attr('placement', placement.join('-'));
};

/**
 * @description: 绑定滚动和改变窗口大小时，重新定位弹出框的位置
 * @param {*}
 * @return {*}
 * @Date: 2022-05-07 15:16:16
 */
Tip.prototype._bindSetPosition = function () {
    let that = this;

    $(window).on('scroll resize', function () {
        _throttle(that._calcPosition(), 200);
    });

    // 监听 特定的容器
    $(this.SCROLL).on('scroll', function () {
        _throttle(that._calcPosition(), 200);
    });
};

export { Tip };
